#include "UI.h"
#include "Ogre.h"
#include "OgreWindowEventUtilities.h"
#include "RendererModules/Ogre/CEGUIOgreRenderer.h"
#include <boost/numeric/conversion/cast.hpp>

// CEGUI includes
#include "CEGUISystem.h"
#include "CEGUIInputEvent.h"
#include "CEGUIWindow.h"
#include "CEGUIWindowManager.h"
#include "CEGUISchemeManager.h"
#include "CEGUIFontManager.h"
#include "elements/CEGUIFrameWindow.h"
#include "ScriptingModules/LuaScriptModule/CEGUILua.h"
#include <CEGUI.h>

//#include "lua.h"
#include "LuaInterface.h"
#include "ScriptingModules/LuaScriptModule/support/tolua++/tolua++.h"
#include "InputManager.h"
#include <string>
template<> UI* Ogre::Singleton<UI>::ms_Singleton = 0;

UI::UI()
: mGUIRenderer(NULL)
, mLayout(NULL)
, mRenderTarget(NULL)
, mSystem(NULL)
, mLuaState(NULL)
, mMouseInWindow(false)
{

}
UI::~UI() {
    lua_close(mLuaState);
}

//void UI::init_old(Ogre::RenderWindow *window) {
//
// ////   Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("GUI");
// //   // new way to instantiate a CEGUIOgreRenderer (Ogre 1.7)
// //   mRenderTarget = window;
// //   mGUIRenderer = &CEGUI::OgreRenderer::bootstrapSystem(*mRenderTarget);
// //   
// //   // create the root CEGUI class
// //   mSystem = CEGUI::System::getSingletonPtr();
//
// //   // tell us a lot about what is going on (see CEGUI.log in the working directory)
// //   CEGUI::Logger::getSingleton().setLoggingLevel(CEGUI::Informative);
//
// //   // Lua
//
// //   mLuaState = lua_open();
// //   tolua_LUAGame_open(mLuaState);
//
// //   CEGUI::LuaScriptModule *pLua = &CEGUI::LuaScriptModule::create(mLuaState);
// //   mSystem->setScriptingModule(pLua);
// //   mSystem->executeScriptFile((CEGUI::utf8*)"init_script.lua", (CEGUI::utf8*)"GUI");
// //   
// //   //mLua->
//
//
// //   //// use this CEGUI scheme definition (see CEGUI docs for more)
// //   //CEGUI::SchemeManager::getSingleton().create((CEGUI::utf8*)"TaharezLookSkin.scheme", (CEGUI::utf8*)"GUI");
//
// //   //// show the CEGUI mouse cursor (defined in the look-n-feel)
// //   //mSystem->setDefaultMouseCursor((CEGUI::utf8*)"TaharezLook", (CEGUI::utf8*)"MouseArrow");
//
// //   //// use this font for text in the UI
// //   //CEGUI::FontManager::getSingleton().create("Tahoma-8.font", (CEGUI::utf8*)"GUI");
// //   //mSystem->setDefaultFont((CEGUI::utf8*)"Tahoma-8");
//
// //   //// load a layout from the XML layout file (you'll find this in resources/gui.zip), and 
// //   //// put it in the GUI resource group
// //   //mLayout = CEGUI::WindowManager::getSingleton().loadWindowLayout("katana.layout", "", "GUI");
//
// //   //mLayout = CEGUI::WindowManager::getSingleton().getWindow("Main");
// //   ////// you need to tell CEGUI which layout to display. You can call this at any time to change the layout to
// //   ////// another loaded layout (i.e. moving from screen to screen or to load your HUD layout). Note that this takes
// //   ////// a CEGUI::Window instance -- you can use anything (any widget) that serves as a root window.
// //   //mSystem->setGUISheet(mLayout);
//    
//}
void UI::init(Ogre::RenderWindow *window) {
    //   Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("GUI");
    // new way to instantiate a CEGUIOgreRenderer (Ogre 1.7)
    // link the ui to the render window
    mRenderTarget = window;
    mGUIRenderer = &CEGUI::OgreRenderer::bootstrapSystem(*mRenderTarget);
    
    // create the root CEGUI class
    mSystem = CEGUI::System::getSingletonPtr();

    // tell us a lot about what is going on (see CEGUI.log in the working directory)
    CEGUI::Logger::getSingleton().setLoggingLevel(CEGUI::Informative);

    CEGUI::Scheme & scheme = CEGUI::SchemeManager::getSingleton().create( "TaharezLook.scheme");

    // Set the defaults
    CEGUI::System::getSingleton().setDefaultFont( "DejaVuSans-10" );

    CEGUI::System::getSingleton().setDefaultMouseCursor( "TaharezLook", "MouseArrow" );

    //CEGUI::Window* myRoot = CEGUI::WindowManager::getSingleton().createWindow( "DefaultWindow", "Root" );
    //CEGUI::System::getSingleton().setGUISheet( myRoot );
}
void UI::load(const std::string &script) {
    //CEGUI::WindowManager::getSingleton().destroyAllWindows();
    //mSystem->executeScriptFile((CEGUI::utf8*)(script.c_str()), (CEGUI::utf8*)"GUI");
    //mLayout = CEGUI::WindowManager::getSingleton().getWindow("Main");
    //mSystem->setGUISheet(mLayout);
}

bool UI::keyPressed( const OIS::KeyEvent &evt ) {
    if (!mSystem)
        return false;
    unsigned int ch = evt.text;
    mSystem->injectKeyDown(evt.key);
    return mSystem->injectChar(ch);
}
bool UI::keyReleased( const OIS::KeyEvent &evt ) {
    if (!mSystem)
        return false;
    return mSystem->injectKeyUp(evt.key);
}

bool UI::mouseMoved( const OIS::MouseEvent &evt ) {
    if (!mSystem)
        return false;
    
    mSystem->injectMouseWheelChange(boost::numeric_cast<float, const int>(evt.state.Z.rel));
    //return mSystem->injectMouseMove(boost::numeric_cast<float, const int>(evt.state.X.rel), 
    //    boost::numeric_cast<float, const int>(evt.state.Y.rel));
    if (mMouseInWindow)
    {
        CEGUI::System::getSingleton().injectMousePosition( evt.state.X.abs, evt.state.Y.abs );
        if (evt.state.X.abs == 0 || evt.state.Y.abs == 0 ||
            evt.state.X.abs == mRenderTarget->getWidth() || evt.state.Y.abs == mRenderTarget->getHeight())
        {
            CEGUI::MouseCursor::getSingleton().hide();
            ShowCursor(true); // windows only
            mMouseInWindow = false;
        }
    }
    else if (evt.state.X.abs > 0 && evt.state.Y.abs > 0 &&
        evt.state.X.abs < boost::numeric_cast<int, unsigned int>(mRenderTarget->getWidth()) && 
        evt.state.Y.abs < boost::numeric_cast<int, unsigned int>(mRenderTarget->getHeight()))
    {
        CEGUI::MouseCursor::getSingleton().show();
        ShowCursor(false); // windows only
        mMouseInWindow = true;
    }

    return mSystem->injectMousePosition(evt.state.X.abs, evt.state.Y.abs);
}
bool UI::mousePressed( const OIS::MouseEvent &evt, OIS::MouseButtonID btn ){
    if (!mSystem)
        return false;
    CEGUI::MouseButton button = CEGUI::NoButton;


    if (btn == OIS::MB_Left)
        button = CEGUI::LeftButton;

    if (btn == OIS::MB_Middle)
        button = CEGUI::MiddleButton;

    if (btn == OIS::MB_Right)
        button = CEGUI::RightButton;

    return mSystem->injectMouseButtonDown(button);
}

bool UI::mouseReleased( const OIS::MouseEvent &evt, OIS::MouseButtonID btn ) {
    if (!mSystem)
        return false;
    CEGUI::MouseButton button = CEGUI::NoButton;

    if (btn == OIS::MB_Left)
        button = CEGUI::LeftButton;

    if (btn == OIS::MB_Middle)
        button = CEGUI::MiddleButton;

    if (btn == OIS::MB_Right)
        button = CEGUI::RightButton;

    return mSystem->injectMouseButtonUp(button);
}
